#!/bin/bash
#
# usage: steering_parallel.sh @MassAxi@100.0,400@param_card.dat@WidAxi_0.2times @gaxi@0.1,0.2_0.1@param_card.dat @htjmin@200,400,600@run_card.dat@+htjmax
#
#help generate_events
#syntax: generate_events [run_name] [options])
#-- Launch the full chain of script for the generation of events
#   Including possible plotting, shower and detector resolution.
#   Those steps are performed if the related program are installed
#   and if the related card are present in the Cards directory.
#-- local options:
#      -f : Use default for all questions.
#      --laststep= : argument might be parton/pythia/pgs/delphes and indicate the last level to be run.
#-- session options:
#      Note that those options will be kept for the current session
#      --cluster : Submit to the  cluster. Current cluster: condor
#      --multicore : Run in multi-core configuration
#      --nb_core=X : limit the number of core to use to X.
# bc -l
# s (x)  The sine of x, x is in radians.
# c (x)  The cosine of x, x is in radians.
# a (x)  The arctangent of x, arctangent returns radians.
# l (x)  The natural logarithm of x.
# e (x)  The exponential function of raising e to the value x.
#
##################################
source $HOME/scriptbelt/bashutilities.sh
##################################

echo -e $BLUE"the output folder will be"
dateofrun=`date +"%Y-%m-%d--%H-%M"`
tempfoldername="$@""__"$dateofrun
outputfolder=`echo output/"$tempfoldername" | sed 's/ /_/g'`
generationsfolder=`echo generations/"$tempfoldername" | sed 's/ /_/g'`
echo $outputfolder
echo -e $COL_RESET

argCounter=1;
leaveruncard=false
leaveparamcard=false
batchrun=false
parallel=false
#diagonalrun=false
therearecapobservables=false
therearedependentobservables=false
#
####### PHYSICS DEFAULTS #########
laststep="parton"
numberofruns=0
dimensions=()
##################################

for iarg in $*; do
    CLIinputs[$argCounter]=$iarg

    if [ "$iarg" == "--help" ]; then
	echo "usage: steering_parallel.sh @MassAxi@100.0,400@param_card.dat@WidAxi_0.2times @gaxi@0.1,0.2_0.1@param_card.dat @htjmin@200,400,600@run_card.dat@+htjmax"
	echo "available options:"
	echo "--parallel"
	echo "--keepruncard"
	echo "--keepparamcard"
	echo  "-f"
	echo "--nb_runs ~ defaut is 0"
	echo "--laststep ~ defaut is parton, available options are parton,pythia,pgs,delphes"
    fi

    if [ "$iarg" == "--parallel" ]; then
	parallel=true
    fi

    if [ "$iarg" == "--keepruncard" ]; then
	leaveruncard=true
    fi

    if [ "$iarg" == "--keepparamcard" ]; then
	leaveparamcard=true
    fi

    if [ "$iarg" == "-f" ]; then
	batchrun=true
    fi

    option=`echo "$iarg" | cut -d"=" -f1`

    if [ "$option" == "--nb_runs" ]; then
	
	numberofruns=`echo "$iarg" | cut -d"=" -f2`
	echo -e "madevent will be run "$RED$numberofruns$COL_RESET" times"
    fi

    # if [ "$option" == "--diagonal" ]; then
    # 	diagonalrun=true
    # 	diagonalparamter=`echo "$iarg" | cut -d"=" -f2`
    # 	echo -e "the paramter "$RED$diagonalparamter$COL_RESET" will be changed together with "$RED$1$COL_RESET
    # fi

    if [ "$option" == "--laststep" ]; then
	
	laststep=`echo "$iarg" | cut -d"=" -f2`
	knownlaststep=false
	case $laststep in
	    parton )
		knownlaststep=true
		echo -e "the last step will be "$RED$laststep$COL_RESET
		;;
	    pythia )
		knownlaststep=true
		echo -e "the last step will be "$RED$laststep$COL_RESET
		;;
	    pgs ) 
		knownlaststep=true
		echo -e "the last step will be "$RED$laststep$COL_RESET
		;;
	    delphes )
		knownlaststep=true
		echo -e "the last step will be "$RED$laststep$COL_RESET
		;;
	esac
	# must be either 	pgs, parton, delphes, pythia
	if [ "$knownlaststep" = false ]; then
	    echo -e "the last step "$laststep" is not known, "$RED"quitting ... "$COL_RESET
	    exit
	fi
    fi

    dimension=`echo "$iarg" | cut -s -d"@" -f2-`
    length=`echo "$dimension" | wc -c`
    if [ $length -gt 1 ]; then
	################# THIS IS A DIMENSION SCAN SPECIFICATION #################
	echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
	echo "Found one dimension for the scan ""$underline$dimension"$nounderline
	obs=`echo "$dimension" | cut -d"@" -f1`
	dimensions+=($obs)
	range=`echo "$dimension" | cut -d"@" -f2`
	rangedivider=`countoccurrencies "$range" _`
	card=`echo "$dimension" | cut -d"@" -f3`
	echo -e "scanning the observable "$RED$obs$COL_RESET" in the card "$RED$card$COL_RESET
	if [ $rangedivider -gt 0 ]; then
	    size=`echo "$range" | cut -d"_" -f2`
	    minmax=`echo "$range" | cut -d"_" -f1`
	    start=`echo "$minmax" | cut -d"," -f1`
	    end=`echo "$minmax" | cut -d"," -f2`

	    binlowends=( `minmaxsize2array $start $end $size` )
	    # binlowends IS WHAT IS NEEDED TO CARRY TO THE NEXT STAGE
	    for ((i=0; i<${#binlowends[@]}; ++i));
	    do
		echo "run $obs $i : ${binlowends[$i]}";
	    done
	    echo -e "the range from "$RED$start$COL_RESET" to "$RED$end$COL_RESET" will be split in bins of size "$RED$size$COL_RESET
	else
	    binlowends=( `csv2array $range` )
	    # binlowends IS WHAT IS NEEDED TO CARRY TO THE NEXT STAGE	    
	    for ((i=0; i<${#binlowends[@]}; ++i));
	    do
		echo "run $obs $i : ${binlowends[$i]}";
	    done
	       
	fi

	#### optional stuff ######
	length=`countoccurrencies "$dimension" @`
	dependentobservables=()
	capobservables=()
	if [ $length -gt 2 ]; then 
	    relatedobs=`echo "$dimension" | cut -d"@" -f4`
	    obsmax=`echo "$relatedobs" | cut -s -d"+" -f2`
	    obsequal=`echo "$relatedobs" | cut -d"+" -f1`
	    lengthobsmax=`echo $obsmax | wc -c`
	    lengthobsequal=`echo $obsequal | wc -c`
	    if [ $lengthobsmax -gt 1 ]; then

		capobservables=( `csv2array $obsmax` )
		#echo ${#capobservables[@]}	
		echo -e "the observable "$RED${capobservables[*]}$COL_RESET" will be set at the value of the following step"
	    fi
	    if [ $lengthobsequal -gt 1 ]; then

		dependentobservables=( `csv2array $obsequal` )
		#echo ${#dependentobservables[@]}	
		echo -e "the observable "$RED${dependentobservables[*]}$COL_RESET" will be set at the value of the following step"
	    fi
	fi
	#############################################################################################################
	################# PUT ON A FILE THE LIST OF CHANGES IN THE CARD THAT NEED TO BE DONE FOR THIS SCAN ##########
	#############################################################################################################
	
	COUNTER=0
	shift=0
	dimensionlength=${#binlowends[@]}
	if [ ${#capobservables[@]} -gt 0 ]; then
	    #echo "there are "${#capobservables[@]}" cap observables"
	    shift=1
	fi
	while [  $COUNTER -lt $(echo $dimensionlength - $shift | bc) ]; do
	    ################## HERE I ALSO PUT THE RELATED OBSERVABLES AND THE CAPOBSERVABLES ##################
	    fundamental=($obs ${binlowends[$COUNTER]} $card )
	    caps=()
	    dependent=()
	    
	    for ((i=0; i < ${#capobservables[@]}; ++i)); 
	    do
		caps+=(${capobservables[$i]});
		caps+=(${binlowends[$COUNTER+1]})
		caps+=($card)
	    done
	    
	    for ((i=0; i < ${#dependentobservables[@]}; ++i)); 
	    do
		dep=`echo ${dependentobservables[$i]} | cut -d"_" -f1`
		operation=`echo ${dependentobservables[$i]} | cut -s -d"_" -f2`
		operationtwo=`echo ${dependentobservables[$i]} | cut -s -d"_" -f3`

		newoperation=`literalintomath $operation`
		operation=$newoperation

		newoperation=`literalintomath $operationtwo`
		operationtwo=$newoperation

		dependent+=($dep);
		dependent+=( $(echo $operation\(${binlowends[$COUNTER]}\)$operationtwo | bc -l) )
		dependent+=($card)
	    done


	    derived=("${dependent[@]}" "${caps[@]}")
	    params=("${fundamental[@]}" "${derived[@]}")


	    if [ $COUNTER = 0 ]; then
		echo ${params[*]} > $obs
	    else
		echo ${params[*]} >> $obs
	    fi

	    let COUNTER=COUNTER+1
	done
    fi

    let argCounter=argCounter+1
done
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
	#echo "The inputs are "${CLIinputs[*]}
echo -e "The scan will span the "${#dimensions[@]}" observables "$RED${dimensions[*]}$COL_RESET

#######################################################################
################ COMBINATION OF ALL THE SCANS #########################
#######################################################################

for ((i=1; i<${#dimensions[@]}; ++i));
do
    if [ $i = 1 ]; then
	#echo ${dimensions[0]} ${dimensions[1]}
	multiplyfiles ${dimensions[0]} ${dimensions[1]} > $i
	sed -i '/^\s*$/d' $i
    else
	#echo $(($i-1)) ${dimensions[$i]}
	multiplyfiles $(($i-1)) ${dimensions[$i]} > $i
	rm $(($i-1))
	sed -i '/^\s*$/d' $i
    fi
done

if [ ${#dimensions[@]} -gt 1 ]; then
    totalscan=$(($i-1))
else
    echo "one dime scan"
    totalscan=${dimensions[0]}
fi

echo -e $RED"Will use the following paramters in the run_cards:"$COL_RESET
echo "reading "$totalscan
cat $totalscan
scansize=`cat $totalscan | wc -l`
echo -e "for a total of "$RED$underline$scansize" runs"$nounderline$COL_RESET
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"

#######################################################################
################ WARNINGS ABOUT THE FILES ##########################
#######################################################################

if [ "$leaveruncard" = true ]; then
    echo -e "The "$RED"run_card"$COL_RESET" will $underline""not be restored$nounderline at the end of the run"
fi
if [ "$leaveparamcard" = true ]; then
    echo -e "The "$RED"param_card"$COL_RESET" will $underline""not be restored$nounderline at the end of the run"
fi

#echo "The inputs are "${CLIinputs[*]}

#######################################################################
################ check and create directories ##########################
#######################################################################
if [ ! -d output ]; then
    # Control will enter here if $DIRECTORY doesn't exist.
    mkdir output
fi

if [ ! -d "$outputfolder" ]; then
    # Control will enter here if $DIRECTORY doesn't exist.
    mkdir $outputfolder
fi

if [ $laststep = pgs ]; then

    if [ ! -d "$outputfolder/pgs/" ]; then
	# Control will enter here if $DIRECTORY doesn't exist.
	mkdir $outputfolder/pgs/
    fi
fi
if [ "$parallel" = true ]; then
    if [ ! -d generations ]; then
	# Control will enter here if $DIRECTORY doesn't exist.
	mkdir generations
    fi

    if [ ! -d "$generationsfolder" ]; then
	# Control will enter here if $DIRECTORY doesn't exist.
	mkdir $generationsfolder
    fi

    launchpad=$PWD
    generationpath="$PWD""_generations/"
    echo -e $RED"THIS WILL BE A PARALLEL RUN"$COL_RESET
    echo -e "launchpad directory: "$RED$launchpad$COL_RESET
    echo -e "generated runs will be stored under the directory: "$RED$generationpath$COL_RESET

fi



#there are runs to be made!
if [ $scansize -gt 0 ]; then 
    rm run_card.dat.run*
    rm param_card.dat.run*
    
    cp Cards/run_card.dat .
    cp Cards/param_card.dat .
    
    cp run_card.dat run_card.dat.original
    cp param_card.dat param_card.dat.original

    # find the run_name in the current run card and prompt if that is ok 
    currentrunname=`grep -e run_tag run_card.dat | cut -d "=" -f1 | tr -d " "`
    defaultrunname=$currentrunname
    if [ "$batchrun" = false ]; then
	echo -e "This is an interactive run"
	####################################
	echo -e "The current run_tag is "$MAGENTA$currentrunname$COL_RESET
	echo -n "use it? (return=yes, or type new one) " && read currentrunname && echo $currentrunname
	baserunname=${currentrunname:-$defaultrunname}
	
	#baserunname=$currentrunname
    else
	baserunname=$defaultrunname
    fi
    
    #scansize will be d1*d2*d3*...*dn if each dimension is sampled d1,d2,d3, ... times
    
	

    COUNTER=1
    while [ $COUNTER -lt $(cat $totalscan | wc -l) ]
    do
	# here I get params from each line of the file $totalscan
	params=( `awk 'NR == n' n=$COUNTER $totalscan` )
   	echo $params
	#let COUNTER=COUNTER+1
	paramsize=${#params[@]}
	
	echo -e $RED"There are "$(echo ${#params[@]}/3 | bc)" changes to be made to the card."
	echo -e ${params[*]}
	echo -e $COL_RESET
	#	eliminate the k=3n components, where the card information is stored. 
	simpleparams=`dropinarray 3 "${params[@]}" `
	runnameappend=`echo -e ${simpleparams[*]} |  sed -e 's/ /_/g'`
	runnames[$COUNTER]=$runnameappend
	echo $runnameappend
	
	
	# write all the cards
	COUNTERparam=0
	while [  $COUNTERparam -lt $paramsize ]; do
	    echo -e $BLUE"Making change "$(($COUNTERparam/3 + 1))":"${params[$COUNTERparam]} ${params[$COUNTERparam+1]}$COL_RESET 
	    
	    # set_madgraph_parameter.sh ${params[$COUNTERparam]} ${params[$COUNTERparam+1]} $card
	    set_madgraph_parameter.sh ${params[$COUNTERparam]} ${params[$COUNTERparam+1]} ${params[$COUNTERparam+2]}
	    let COUNTERparam=COUNTERparam+3 
	done
	# run_tag is always updated in the run_card.dat
	set_madgraph_parameter.sh  run_tag $baserunname"_run"$(($COUNTER+1))"_"$runnameappend run_card.dat
	# since run_tag is always updated the run_card needs to be changed in all runs
	cp run_card.dat run_card.dat.run$COUNTER
	# if param_card.dat was modified prepare the param_card.dat
	if [ "$card" = "param_card.dat" ]; then 
	    cp param_card.dat param_card.dat.run$COUNTER
	fi
	
	let COUNTER=COUNTER+1 
	
    done
    #########################################################################################
    ############################ ALL THE CARDS HAVE BEEN WRITTEN ############################
    #########################################################################################
    #
    writetag p "My text is here"
    exit
    ####################################
    # copy the cards and run one by one (or send it in many places, but not yet in this version!)
    ####################################
    # the difference is that in order to run parallel the folder needs to be duplicted each time and the cards need to be run in that folder in parallel
    # using xargs? or parallel? I don't know yet
    
    launchpad=$PWD

    COUNTER=1
    while [  $COUNTER -le $(echo $scansize | bc) ]; do
	if [ "$card" = "param_card.dat" ]; then 
	    cp  param_card.dat.run$(($COUNTER-1)) Cards/param_card.dat
	fi
	cp run_card.dat.run$(($COUNTER-1)) Cards/run_card.dat


	if [ $numberofruns -gt 0 ]; then
	    if [ $numberofruns -eq 1 ]; then
		MGrunname="run"$COUNTER"_of_"$scansize"__"${runnames[$(($COUNTER-1))]}"__"$dateofrun
	        ./bin/generate_events $MGrunname  -f --laststep=$laststep
		#		if [ "$newobsmax" != "" ]; then
		cd Events/$MGrunname
		outputfilename=`ls *.txt | rev | cut -d"." -f2- | cut -c8- | rev`
		cd ../..
		ln -v -s ../../Events/$MGrunname/unweighted_events.root ./$outputfolder/$outputfilename.root
		if [ $laststep = pgs ]; then
		    ln -v -s ../../Events/$MGrunname/*.lhco.lhe.root ./$outputfolder/pgs/
		fi
		#		fi
	    else 
		./bin/madevent multi_run $numberofruns -f --laststep=$laststep 
	    fi
	fi
	
	let COUNTER=COUNTER+1 
    done
    
    
    ######################################################################################
    ############################       RESTONE THE CARDS      ############################
    ######################################################################################
    
    if [ "$leaveruncard" = false ]; then
	echo -e $RED"The run_card.dat is going to be restored."
	cp -v run_card.dat.original ./Cards/run_card.dat
	echo -e $COL_RESET
    fi

    if [ "$leaveparamcard" = false ]; then
	echo -e $RED"The param_card.dat is going to be restored."
	cp -v param_card.dat.original ./Cards/param_card.dat
	echo -e $COL_RESET
    fi
    	
fi
